package com.ljn.data.service;

import com.ljn.data.entity.SearchParam;
import com.ljn.data.exception.AisFacadeExceptionCode;
import com.ljn.data.exception.aisFacadeException;
import com.ljn.data.utils.SpringContext;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.ljn.data.dao.ElasticsearchApi;
import com.ljn.data.domain.AiService;
import com.ljn.data.entity.AiResource;
import com.ljn.data.utils.FileReadUtil;
import com.ljn.data.utils.PropertiesMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

@Service("aiService")
public class AiServiceImpl implements AiService {


    private static final Logger log = LoggerFactory.getLogger(AiServiceImpl.class);

    private static final String ELASTICSEARCH_API = "elasticsearchApi";

    private static final String AI_SERVICE_INDEX = "ai_service_index";

    private static final String AI_SERVICE = "ai_service";

    private static final String ASTERISK = "*";
    private static final Integer DISABLED = 0;
    private static final String ESERROR = "--es操作异常---";
    private static final Long MAX_SIZE = 1000L;

    @Override
    public void addResource(List<AiResource> esSearchDatas) {

        if(!CollectionUtils.isEmpty(esSearchDatas)){
            try {
                log.info("---------批量新增/更新答案资源中-----------");
                if(!CollectionUtils.isEmpty(esSearchDatas)) {
                    Map<String,String> map = Maps.newHashMap();
                    for(AiResource aiResource : esSearchDatas) {
                        map.put(aiResource.getId().toString(), JSONObject.toJSONString(aiResource));
                    }
                    ElasticsearchApi elasticsearchApi = (ElasticsearchApi) SpringContext.getBean(ELASTICSEARCH_API);
                    BulkRequest bulkRequest = elasticsearchApi.bulkRequest(AI_SERVICE_INDEX, AI_SERVICE, map);
                    elasticsearchApi.bulkIndex(bulkRequest);
                }

                log.info("---------批量新增/更新答案资源成功-----------");
            } catch (Exception e) {
                log.error(ESERROR, e);
            }

        }
    }
    
    @Override
    public void updateResource(String id,AiResource resource){
    	  if(!StringUtils.isEmpty(id) && resource!=null){
              Map<String,String> map = Maps.newHashMap();
              map.put(id, JSONObject.toJSONString(resource));
              try {
            	   ElasticsearchApi elasticsearchApi = (ElasticsearchApi) SpringContext.getBean(ELASTICSEARCH_API);
                   elasticsearchApi.exeUpdate(AI_SERVICE_INDEX, AI_SERVICE, map);
              } catch (Exception e) {
                  log.error(ESERROR, e);
              }
    	  }
    }
    
    @Override
    public void  delResource(List<String> ids){
        log.info("---------根据ids批量删除答案资源中-----------");
        if(!CollectionUtils.isEmpty(ids)) {
            try {
                ElasticsearchApi elasticsearchApi = (ElasticsearchApi) SpringContext.getBean(ELASTICSEARCH_API);
                elasticsearchApi.delDocumentByIds(AI_SERVICE_INDEX, AI_SERVICE, ids);
            } catch (Exception e) {
                log.error(ESERROR, e);
            }
            log.info("---------根据ids批量删除答案资源成功-----------");
        }

    }
    @Override
    public List<AiResource> getResourceByKeyWord(String keyWord){
        List<AiResource> aiResourceList = Lists.newArrayList();
        if(!StringUtils.isEmpty(keyWord)){
            try {
                SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
                boolBuilder.should(QueryBuilders.wildcardQuery("keyWord", ASTERISK + keyWord + ASTERISK));
                boolBuilder.must(QueryBuilders.matchQuery("status",0));
                sourceBuilder.query(boolBuilder);
                //执行搜索
                ElasticsearchApi elasticsearchApi = (ElasticsearchApi) SpringContext.getBean(ELASTICSEARCH_API);
                SearchResponse searchResponse = elasticsearchApi.exeSearch(AI_SERVICE_INDEX, AI_SERVICE, sourceBuilder);
                if(searchResponse == null) {
                    return aiResourceList;
                }
                // 封装查询结果
                SearchHits hits = searchResponse.getHits();
                if(hits.getHits() != null && hits.getHits().length > 0) {
                    for (SearchHit searchHit : hits.getHits()) {
                        String source = searchHit.getSourceAsString();
                        AiResource temp = JSONObject.parseObject(source, AiResource.class);
                        aiResourceList.add(temp);
                    }
                }
            } catch (Exception e) {
                log.error(ESERROR, e);
            }

        }
        return aiResourceList;
    }
    
    @Override
	public List<AiResource> getResourceByQuestion(String question)
	{
    	List<AiResource> aiResourceList = Lists.newArrayList();
    	if(!StringUtils.isEmpty(question)) {
	    	SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
	    	BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
	    	boolBuilder.must(QueryBuilders.wildcardQuery("question", ASTERISK + question + ASTERISK));
	    	sourceBuilder.query(boolBuilder);
	    	 try {
	 	    	//执行搜索
	             ElasticsearchApi elasticsearchApi = (ElasticsearchApi) SpringContext.getBean(ELASTICSEARCH_API);
	             SearchResponse searchResponse = elasticsearchApi.exeSearch(AI_SERVICE_INDEX, AI_SERVICE, sourceBuilder);
	             if(searchResponse == null) {
	                 return aiResourceList;
	             }
	             // 封装查询结果
	             SearchHits hits = searchResponse.getHits();
	             if(hits.getHits() != null && hits.getHits().length > 0) {
	                 for (SearchHit searchHit : hits.getHits()) {
	                     String source = searchHit.getSourceAsString();
	                     AiResource temp = JSONObject.parseObject(source, AiResource.class);
	                     aiResourceList.add(temp);
	                 }
	             }
	 	    	
	 	    } catch (Exception e) {
	             log.error(ESERROR, e);
	         }
    	}
		return aiResourceList;
	}
    
    @Override
    public List<AiResource> queryPageResource(SearchParam param,Integer pageNo,Long pageSize){
    	List<AiResource> aiResourceList = Lists.newArrayList();
		SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
		Long start = 0L;
		Long row = 10L;
		if(pageSize != null) {
			row = pageSize;
		}
		if(pageNo!=null) {
			start = (pageNo-1)*row;
		}
//		sourceBuilder.from(start.intValue());
//		sourceBuilder.size(row.intValue());
		sourceBuilder.size(MAX_SIZE.intValue());
	    BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
	    if(!StringUtils.isEmpty(param.getAnswer())) {
	    	boolBuilder.must(QueryBuilders.wildcardQuery("answer", ASTERISK + param.getAnswer() + ASTERISK));
	    }
	    if(param.getDisabled()!=null) {
	    	boolBuilder.filter(QueryBuilders.termQuery("disabled",  param.getDisabled()));
	    }
	    if(!StringUtils.isEmpty(param.getKeyword())) {
	    	boolBuilder.must(QueryBuilders.wildcardQuery("keyword", ASTERISK + param.getKeyword() + ASTERISK));
	    }
	    if(!StringUtils.isEmpty(param.getQuestion())) {
	    	boolBuilder.must(QueryBuilders.wildcardQuery("question", ASTERISK + param.getQuestion() + ASTERISK));
	    }
	    if(!StringUtils.isEmpty(param.getSysModule())) {
	    	boolBuilder.must(QueryBuilders.wildcardQuery("sysModule", ASTERISK + param.getSysModule() + ASTERISK));
	    }
	    if(param.getSysType()!=null) {
	    	boolBuilder.filter(QueryBuilders.termQuery("sysType", param.getQuestion()));
	    }
	    if(param.getStartTime()!=null && param.getEndTime()!=null) {
	    	boolBuilder.must(QueryBuilders.rangeQuery("createTime").gte(param.getStartTime()).lte(param.getEndTime()));
	    }
	    sourceBuilder.query(boolBuilder);
	    //是否查询全部，默认只有10000
	    sourceBuilder.trackTotalHits(true);
	    try {
	    	//执行搜索
            ElasticsearchApi elasticsearchApi = (ElasticsearchApi) SpringContext.getBean(ELASTICSEARCH_API);
            SearchResponse searchResponse = elasticsearchApi.exeSearch(AI_SERVICE_INDEX, AI_SERVICE, sourceBuilder);
            if(searchResponse == null) {
                return aiResourceList;
            }
            // 封装查询结果
            SearchHits hits = searchResponse.getHits();
            if(hits.getHits() != null && hits.getHits().length > 0) {
                for (SearchHit searchHit : hits.getHits()) {
                    String source = searchHit.getSourceAsString();
                    AiResource temp = JSONObject.parseObject(source, AiResource.class);
                    aiResourceList.add(temp);
                }
            }
	    	
	    } catch (Exception e) {
            log.error(ESERROR, e);
        }
    	return aiResourceList;
    }

    @Override
    public List<AiResource> uploadResource(byte[] bytes, String fileName, String filePath, Long userId, String remark,
       Long creatorId, String creatorName){
        log.error("上传文件开始");
        Map<String, List<AiResource>> dataMap = null;
        // 知识库解析DTO列表
        List<AiResource> dto = new ArrayList<>();
        List<AiResource> esSearchDatas = new ArrayList<>();
        //文件类型检验
        if (!checkFileType(fileName))
        {
          throw new aisFacadeException(AisFacadeExceptionCode.RESOURCE_FILE_PATTERN_ERROR, "资源文件格式错误");
        }
        // 校验文件大小
        if (!checkFileSize(bytes))
        {
            throw new aisFacadeException(AisFacadeExceptionCode.RESOURCE_FILE_LONG, "资源文件大小超过5M");
        }
        InputStream inputStream = new ByteArrayInputStream(bytes);
        try
        {
          
            dataMap = FileReadUtil.importFile(inputStream, PropertiesMap.getTitleMap(), fileName, AiResource.class);
            
        }
        catch (IOException e)
        {
            throw new aisFacadeException(AisFacadeExceptionCode.RESOURCE_FILE_ANALYSE_ERROR);
        }
        if (dataMap != null && dataMap.size() > 0)
        {
            for (Entry<String, List<AiResource>> entry : dataMap.entrySet())
            {  
                dto.addAll(entry.getValue());
            }
        }
        
        //数据处理
        Long id = getMaxId();
        if(!CollectionUtils.isEmpty(dto)){
            for (AiResource aiResource : dto)
            {
                long createTime = 0;
                AiResource resource = new AiResource();
                resource.setSysType(aiResource.getSysType());
                resource.setSysModule(aiResource.getSysModule());
                resource.setKeyword(aiResource.getKeyword());
                resource.setQuestion(aiResource.getQuestion());
                resource.setAnswer(aiResource.getAnswer());
                resource.setMsgLink(aiResource.getMsgLink());
                resource.setCreator(aiResource.getCreator());
                resource.setDisabled(DISABLED);
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                try {
                    createTime = dateFormat.parse(dateFormat.format(new Date())).getTime();
                } catch (ParseException e) {
                    log.info("获取时间失败"+e);
                }
                resource.setCreateTime(createTime);
                id = id +1;
                resource.setId(id);
                esSearchDatas.add(resource);
            }
        }
        
        try {
            //增加数据至es
            addResource(esSearchDatas);

        } catch (Exception e) {
            log.info("调用addResource接口失败"+e);
        }
        
        return esSearchDatas;
    }

    
    /**
     * @description: 文件格式校验
     * @param fileName
     * @return
     *      @author： DELL
     * @createTime：2016年4月8日 上午10:09:07
     */
    public boolean checkFileType(String fileName)
    {

        return (fileName.endsWith("xls") || fileName.endsWith("xlsx"));
    }
    
    /**
     * @description: 校验文件大小
     * @param bytes
     * @return
     *      @author： DELL
     * @createTime：2016年4月8日 上午10:20:57
     */
    public boolean checkFileSize(byte[] bytes)
    {

        return bytes.length <= 5 * 1024 * 1024;
    }

    @Override
    public Long getMaxId() {
        Long maxId = 0L;
        try {
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
            sourceBuilder.size(MAX_SIZE.intValue());
            sourceBuilder.query(boolBuilder);
            //执行搜索
            ElasticsearchApi elasticsearchApi = (ElasticsearchApi) SpringContext.getBean(ELASTICSEARCH_API);
            SearchResponse searchResponse = elasticsearchApi.exeSearch(AI_SERVICE_INDEX, AI_SERVICE, sourceBuilder);
            if(searchResponse == null) {
                return maxId;
            }
            // 封装查询结果
            SearchHits hits = searchResponse.getHits();
            if(hits.getHits() != null && hits.getHits().length > 0) {
                for (SearchHit searchHit : hits.getHits()) {
                    String source = searchHit.getSourceAsString();
                    AiResource temp = JSONObject.parseObject(source, AiResource.class);
                    if (temp.getId() != null) {
                        Long id = temp.getId();
                        if(maxId < id) {
                            maxId = id;
                        }
                    }
                    
                }
            }
        } catch (Exception e) {
            System.out.println("+++++++++++++++++++++++++++++++"+e);
            log.error(ESERROR, e);
        }
        return maxId;
    }

    @Override
    public AiResource getResourceById(String id) {
        AiResource resource = new AiResource();
        if(!StringUtils.isEmpty(id)) {
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
            boolBuilder.must(QueryBuilders.matchQuery("id",id));
            sourceBuilder.query(boolBuilder);
             try {
                //执行搜索
                 ElasticsearchApi elasticsearchApi = (ElasticsearchApi) SpringContext.getBean(ELASTICSEARCH_API);
                 SearchResponse searchResponse = elasticsearchApi.exeSearch(AI_SERVICE_INDEX, AI_SERVICE, sourceBuilder);
                 if(searchResponse == null) {
                     return resource;
                 }
                 // 封装查询结果
                 SearchHits hits = searchResponse.getHits();
                 if(hits.getHits() != null && hits.getHits().length > 0) {
                     for (SearchHit searchHit : hits.getHits()) {
                         String source = searchHit.getSourceAsString();
                         AiResource temp = JSONObject.parseObject(source, AiResource.class);
                         resource = temp;
                     }
                 }
                
            } catch (Exception e) {
                 log.error(ESERROR, e);
             }
        }
        return resource;
    }






}
